﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PloobsEngine;
using PloobsEngine.Cameras;
using PloobsEngine.Light;
using PloobsEngine.Material;
using PloobsEngine.Modelo;
using PloobsEngine.Physics;
using PloobsEngine.Physics.Bepu;
using PloobsEngine.SceneControl;
using PloobsProjectTemplate.Level;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using BEPUphysics.Vehicle;

namespace PloobsProjectTemplate.TemplateScreens
{
    class FirstScreen : IScene
    {

        Maze maze;

        ICamera cam1, cam2;

       Vehicle spaceship;

        IObject obj;

        //ProjectTemplate.BasicCamera camera;

        float moveScale = 2.5f;
        float rotateScale = MathHelper.PiOver2;
        
        protected override void SetWorldAndRenderTechnich(out IRenderTechnic renderTech, out IWorld world)
        {
            
            world = new IWorld(new BepuPhysicWorld(), new SimpleCuller());

            ///Create the deferred description
            DeferredRenderTechnicInitDescription desc = DeferredRenderTechnicInitDescription.Default();
            ///Some custom parameter, this one allow light saturation. (and also is a pre requisite to use hdr)
            desc.UseFloatingBufferForLightMap = true;
            ///set background color, default is black
            desc.BackGroundColor = Color.CornflowerBlue;
            ///create the deferred technich
            renderTech = new DeferredRenderTechnic(desc);

           
        }

        protected override void LoadContent(PloobsEngine.Engine.GraphicInfo GraphicInfo, PloobsEngine.Engine.GraphicFactory factory, IContentManager contentManager)
        {
                
            base.LoadContent(GraphicInfo, factory, contentManager);

            
            #region Models
                SimpleModel nave = new SimpleModel(factory, "Nave/Space_Shooter");  
                
            #endregion  

            ///Uncoment to Add an object
            /////Create a simple object
            /////Geomtric Info and textures (this model automaticaly loads the texture)
            //SimpleModel simpleModel = new SimpleModel(factory, "Model FILEPATH GOES HERE", "Diffuse Texture FILEPATH GOES HERE -- Use only if it is not embeded in the Model file");            
            /////Physic info (position, rotation and scale are set here)
            TriangleMeshObject tmesh = new TriangleMeshObject(nave, Vector3.Zero, Matrix.Identity, Vector3.One, MaterialDescription.DefaultBepuMaterial());
            /////Shader info (must be a deferred type)
            DeferredNormalShader shader = new DeferredNormalShader();
            /////Material info (must be a deferred type also)
            DeferredMaterial fmaterial = new DeferredMaterial(shader);
            /////The object itself
            obj = new IObject(fmaterial, nave, tmesh);

            obj.PhysicObject.AngularVelocity = new Vector3(0.5f, 0.5f, 0.5f);
            /////Add to the world
            this.World.AddObject(obj);

            

            ///Add some directional lights to completely iluminate the world
            #region Lights

            DirectionalLightPE ld1 = new DirectionalLightPE(Vector3.Left, Color.White);
            DirectionalLightPE ld2 = new DirectionalLightPE(Vector3.Right, Color.White);
            DirectionalLightPE ld3 = new DirectionalLightPE(Vector3.Backward, Color.White);
            DirectionalLightPE ld4 = new DirectionalLightPE(Vector3.Forward, Color.White);
            DirectionalLightPE ld5 = new DirectionalLightPE(Vector3.Down, Color.White);
            float li = 0.4f;
            ld1.LightIntensity = li;
            ld2.LightIntensity = li;
            ld3.LightIntensity = li;
            ld4.LightIntensity = li;
            ld5.LightIntensity = li;
            this.World.AddLight(ld1);
            this.World.AddLight(ld2);
            this.World.AddLight(ld3);
            this.World.AddLight(ld4);
            this.World.AddLight(ld5);

            #endregion

            cam1 = new CameraStatic(new Vector3(0.5f, 0.5f, 0.5f), new Vector3(0,0.5f,1));
            cam1.NearPlane = 0.05f;
            cam1.FarPlane = 100f;
            cam1.Rotation = Quaternion.Identity;
            cam1.FieldOfView = MathHelper.PiOver4;
            cam1.AspectRatio = GraphicInfo.Viewport.AspectRatio;

            cam2 = new CameraFollowObject(obj, new Vector3(0,0,1));
            //cam2 = new CameraFollowObject(obj, -10, 130);

            //camera = new ProjectTemplate.BasicCamera();
            //camera.Position = new Vector3(0.5f, 0.5f, 0.5f);
            //camera.NearPlane = 0.05f;
            //camera.FarPlane = 100f;
            //camera.Rotation = 0;
            //camera.ApertureAngle = MathHelper.PiOver4;
            //camera.ScreenRatio = GraphicInfo.Viewport.AspectRatio;
        
            //maze = new Maze(ProjectTemplate.EngineSetup.graphicsDevice);
            maze = new Maze();

            ///Add a AA post effect
            this.RenderTechnic.AddPostEffect(new AntiAliasingPostEffect());

            ///add a camera
            //this.World.CameraManager.AddCamera(new CameraFirstPerson(GraphicInfo.Viewport));
            //this.World.CameraManager.AddCamera(new CameraFirstPerson(GraphicInfo));
            //this.World.CameraManager.AddCamera(cam1);
            this.World.CameraManager.AddCamera(cam2);
        }

        protected override void Draw(GameTime gameTime, RenderHelper render)
        {
            base.Draw(gameTime, render);

            maze.Draw(cam1, this.GraphicFactory.GetBasicEffect());

            

        }

        protected override void Update(GameTime gameTime)
        {
            //tempo que passou desde o último update
            float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
            float moveAmount = 0;
            KeyboardState teclado_atual = Keyboard.GetState();

            if (teclado_atual.IsKeyDown(Keys.A) || teclado_atual.IsKeyDown(Keys.Left))
            {
                obj.PhysicObject.Rotation = Matrix.CreateRotationY(this.rotateScale * 1000 * elapsed);
                cam1.Rotation = new Quaternion(cam1.Rotation.X, MathHelper.WrapAngle(cam1.Rotation.Y + (this.rotateScale * 100 * elapsed)), cam1.Rotation.Z, cam1.Rotation.W);
            }

            else if (teclado_atual.IsKeyDown(Keys.D) || teclado_atual.IsKeyDown(Keys.Right))
            {
                cam1.Rotation = new Quaternion(cam1.Rotation.X, MathHelper.WrapAngle(cam1.Rotation.Y - (this.rotateScale * elapsed)), cam1.Rotation.Z, cam1.Rotation.W);
            }

            if (teclado_atual.IsKeyDown(Keys.Up))
            {
                //camera.MoveForward(moveScale * elapsed);
                moveAmount = moveScale * elapsed;
            }

            else if (teclado_atual.IsKeyDown(Keys.S) || teclado_atual.IsKeyDown(Keys.Down))
            {
                //camera.MoveForward(-moveScale * elapsed);
                moveAmount = -moveScale * elapsed;
            }

            if (moveAmount != 0)
            {
                //Vector3 location = cam1.PreviewMove(moveAmount);
                Vector3 location = new Vector3(cam1.Position.X, cam1.Position.Y, cam1.Position.Z + moveAmount);
                bool moveOk = true;

                if (location.X < 0 || location.X > Maze.mazeWidth)
                    moveOk = false;
                if (location.Z < 0 || location.Z > Maze.mazeWidth)
                    moveOk = false;

                if (moveOk)
                    cam1.Position = location;
                //cam1.MoveForward(moveAmount);
            }
            base.Update(gameTime);
        }
    }
}

